package com.generate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;

import com.database.ColumnsVo;
import com.database.DataBaseService;
import com.util.CodeResourceUtil;
import com.util.CodeStringUtils;
import com.util.ResourceUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.utility.DateUtil;

public class CodeFactory {
	private static final Logger logger = Logger.getLogger(CodeFactory.class);
	
	/** 选择的文件夹路径 */
	public static String generateFilePath = "";

	public void generateFile(String templateFileName, String type, Map data,String definePackage) {
		try {
//			String entityPackage = data.get("entityPackage").toString();
//			String bussPackage = data.get("bussPackage").toString();
			String entityName = data.get("entityName").toString();
			
			String fileDir = "";
			String fileNamePath = "";
			if(StringUtils.isEmpty(generateFilePath)){
				fileNamePath = getCodePath(type, definePackage, entityName);
				fileDir = StringUtils.substringBeforeLast(fileNamePath, "/");
				System.out.println("fileNamePath:"+fileNamePath);
				System.out.println("fileDir:"+fileDir);
			}else{
//				entityPackage = bussPackage +File.separator +entityPackage;
				
				if(StringUtils.isNotEmpty(definePackage)){
					definePackage = definePackage.replace(".", File.separator);
				}
				
				fileNamePath = getLocalCodePath(type,  definePackage, entityName);
				fileDir  =StringUtils.substringBeforeLast(fileNamePath, File.separator );
				System.out.println("fileNamePath1:"+fileNamePath);
				System.out.println("fileDir1:"+fileDir);
			}
			
			
			Template template = getConfiguration().getTemplate(templateFileName);
			FileUtils.forceMkdir(new File(fileDir + File.separator));
			Writer out = new OutputStreamWriter(new FileOutputStream(fileNamePath), CodeResourceUtil.SYSTEM_ENCODING);
			template.process(data, out);
			out.close();
		} catch (TemplateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Configuration getConfiguration() {
		Configuration cfg = new Configuration();
		try {
			cfg.setClassForTemplateLoading(getClass(), CodeResourceUtil.FREEMARKER_CLASSPATH);
			cfg.setLocale(Locale.CHINA);
			cfg.setDefaultEncoding("UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cfg;
	}

	public static String getProjectPath() {
		String path = System.getProperty("user.dir").replace("\\", "/") + "/";
		return path;
	}

	public String getClassPath() {
		String path = Thread.currentThread().getContextClassLoader().getResource("./").getPath();
		return path;
	}

	public String getTemplatePath() {
		String path = getClassPath() + CodeResourceUtil.TEMPLATEPATH;
		return path;
	}

	public String getCodePath(String type, String entityPackage, String entityName) {
		String path = getProjectPath();
		StringBuilder str = new StringBuilder();
		if (StringUtils.isNotBlank(type)) {
			String codeType = ((CodeType) Enum.valueOf(CodeType.class, type)).getValue();
			str.append(path);
			if (("jsp".equals(type)) || ("jspList".equals(type)))
				str.append(CodeResourceUtil.JSPPATH);
			else {
				str.append(CodeResourceUtil.CODEPATH);
			}
			if ("Action".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("action"));
			else if ("ServiceImpl".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("service/impl"));
			else if ("ServiceI".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("service"));
			else if (!"List".equalsIgnoreCase(codeType)) {
				str.append(StringUtils.lowerCase(codeType));
			}
			str.append(File.separator);
			str.append(StringUtils.lowerCase(entityPackage));
			str.append(File.separator);

			if (("jsp".equals(type)) || ("jspList".equals(type))) {
				String jspName = StringUtils.capitalize(entityName);

				str.append(CodeStringUtils.getInitialSmall(jspName));
				str.append(codeType);
				str.append(".jsp");
			} else {
				str.append(StringUtils.capitalize(entityName));
//				str.append(codeType);
				str.append(".java");
			}
		} else {
			throw new IllegalArgumentException("type is null");
		}
		return str.toString();
	}
	
	public String getLocalCodePath(String type, String entityPackage, String entityName) {
		String path = CodeFactory.generateFilePath;
		StringBuilder str = new StringBuilder();
		if (StringUtils.isNotBlank(type)) {
			String codeType = ((CodeType) Enum.valueOf(CodeType.class, type)).getValue();
			str.append(path);
			str.append(File.separator);
			if (("jsp".equals(type)) || ("jspList".equals(type)))
				str.append(CodeResourceUtil.JSPPATH);
			else {
				str.append(CodeResourceUtil.CODEPATH);
			}
			str.append(File.separator);
			
			if ("Action".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("action"));
			else if ("ServiceImpl".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("service/impl"));
			else if ("ServiceI".equalsIgnoreCase(codeType))
				str.append(StringUtils.lowerCase("service"));
			else if ("List".equalsIgnoreCase(codeType)) {
				str.append(StringUtils.lowerCase(codeType));
			}else if ("Entity".equalsIgnoreCase(codeType)) {
//				str.append(StringUtils.lowerCase(codeType));
			}
			str.append(File.separator);
			str.append(StringUtils.lowerCase(entityPackage));
			str.append(File.separator);

			if (("jsp".equals(type)) || ("jspList".equals(type))) {
				String jspName = StringUtils.capitalize(entityName);

				str.append(CodeStringUtils.getInitialSmall(jspName));
				str.append(codeType);
				str.append(".jsp");
			} else {
//				str.append(StringUtils.capitalize(entityName));
				str.append(entityName);
//				str.append(codeType);
				str.append(".java");
			}
		} else {
			throw new IllegalArgumentException("type is null");
		}
		return str.toString();
	}

	public static enum CodeType {
		serviceImpl("ServiceImpl"), service("ServiceI"), controller("Controller"), entity("Entity"), jsp(""), jspList("List");

		private String type;

		private CodeType(String type) {
			this.type = type;
		}

		public String getValue() {
			return this.type;
		}
	}
	
	public static void genernateEntity(String tableCode,String tableZhName,String entityName,String definePackage){
		try {
			CodeFactory cf = new CodeFactory();
			Map data = new HashMap();
			data.put("definePackage", definePackage);
//			data.put("entityPackage", "user");
			data.put("entityName", entityName);
//			data.put("bussPackage", "com");
			data.put("packageStyle", CodeType.entity.toString());
			data.put("tableName", tableCode); // 读取数据库

			data.put("ftl_description",tableZhName); // 读取数据库
			data.put("pk_table_Id", "id"); // 读取数据库

			List<ColumnsVo> ls_column = new DataBaseService().getColumnsByTableCode(tableCode.toUpperCase());
			

			data.put("columns", ls_column);
			
			Map fileMetas = new HashMap();
			for (ColumnsVo columnsVo : ls_column) {
				fileMetas.put(columnsVo.getCode(),columnsVo.getCode());
			}
			
			data.put("fieldMeta", fileMetas);

			String type = CodeType.entity.toString();
			String templateFileName = ResourceUtil.getConfigByName("templetname");

			cf.generateFile(templateFileName, type, data,definePackage);

		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}
	

	public static void main(String[] args) {
		try {

			CodeFactory cf = new CodeFactory();

			Map data = new HashMap();
			data.put("entityPackage", "test");
			data.put("entityName", "Test");
			data.put("bussiPackage", "testentity");
			data.put("bussiPackage", "test.java");
			data.put("packageStyle", CodeType.entity.toString());
			data.put("tableName", "t_biz_test"); // 读取数据库

			data.put("ftl_description", "用户属性信息"); // 读取数据库
			data.put("pk_table_Id", "id"); // 读取数据库

			List<ColumnsVo> ls_column = new DataBaseService().getColumnsByTableCode("test2".toUpperCase());
			
			// 读取数据库
//			Columns c2 = new Columns("主键", "Y", "Long", "Id", "N", 0, 0);
//			Columns c = new Columns("姓名", "Y", "String", "userName", "Y", 1, 20);
//			Columns c1 = new Columns("性别", "Y", "String", "userSex", "Y", 1, 20);
//			ArrayList list = new ArrayList();
//			list.add(c);
//			list.add(c1);
//			list.add(c2);

			data.put("columns", ls_column);
			
			Map fileMetas = new HashMap();
			for (ColumnsVo columnsVo : ls_column) {
				fileMetas.put(columnsVo.getCode(),columnsVo.getCode());
			}
//			fileMetas.put("userName", "user_Name");
//			fileMetas.put("userSex", "user_sex");
//			fileMetas.put("Id", "Id");

			data.put("fieldMeta", fileMetas);

			String type = CodeType.entity.toString();
			String templateFileName = "cgform_entityTemplate.ftl";

			cf.generateFile(templateFileName, type, data,"com.user");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
